package com.yykj.bank.server.service.impl;

import com.yykj.bank.client.dto.BankVerifyDTO;
import com.yykj.bank.client.vo.BankVerifyResultVO;
import com.yykj.bank.server.model.entity.BankCardChekLog;
import com.yykj.bank.server.model.repository.BankCardChekLogRepository;
import com.yykj.bank.server.service.BankCardCheckService;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.util.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class BankCardCheckServiceImpl implements BankCardCheckService {

    @Value("${bank-verify.appCode}")
    private String appcode;

    private BankCardChekLogRepository logRepository;

    @Override
    public BankVerifyResultVO verify(BankVerifyDTO dto) {
        BankVerifyResultVO resultVO = doLocalVerify(dto);
        if (resultVO.getCode() != 0) {
            log.info("本地检查失败 {}",dto.getAccountNo());
            resultVO = doRemoteVerify(dto);
            if(resultVO.getCode() == 0){
                log.info("远程检查成功 {}",dto.getAccountNo());
                BankCardChekLog bankCardChekLog = new BankCardChekLog();
                BeanUtils.copyProperties(resultVO, bankCardChekLog);
                BeanUtils.copyProperties(dto, bankCardChekLog);
                logRepository.save(bankCardChekLog);
                log.info("保存远程检查记录 {}",dto.getAccountNo());
                BeanUtils.copyProperties(bankCardChekLog, resultVO);
            }else{
                log.info("远程检查失败 {}",dto.getAccountNo());
            }
        }else{
            log.info("本地检查成功 {}",dto.getAccountNo());
        }
        log.info("检查结束 {}",dto.getAccountNo());
        return resultVO;
    }

    @Override
    public BankVerifyResultVO doRemoteVerify(BankVerifyDTO dto) {
        String host = "https://tbank.market.alicloudapi.com";// 【1】请求地址 支持http 和 https 及 WEBSOCKET
        String path = "/bank4RealCheck";  // 【2】后缀
        String errorMsg;
        BankVerifyResultVO resultVO;
        try {
            String urlSend = host + path + "?idCard=" + dto.getIdCard() + "&name=" + URLEncoder.encode(dto.getName(), "UTF-8")
                    + "&accountNo=" + dto.getAccountNo() + "&mobile=" + dto.getMobile();  // 【5】拼接请求链接
            URL url = new URL(urlSend);
            HttpURLConnection httpURLCon = (HttpURLConnection) url.openConnection();
            httpURLCon.setRequestProperty("Authorization", "APPCODE " + appcode);// 格式Authorization:APPCODE (中间是英文空格)
            int httpCode = httpURLCon.getResponseCode();
            if (httpCode == 200) {
                String json = read(httpURLCon.getInputStream());
                log.info("远程获取json =  {}",json);
                resultVO = GsonUtil.fromJson(json, BankVerifyResultVO.class);
                if ("01".equals(resultVO.getStatus())) {
                    resultVO.setCode(0);
                } else {
                    resultVO.setCode(100);
                }
                return resultVO;
            } else {
                Map<String, List<String>> map = httpURLCon.getHeaderFields();
                String error = map.get("X-Ca-Error-Message").get(0);
                if (httpCode == 400 && "Invalid AppCode `not exists`".equals(error)) {
                    errorMsg = "AppCode错误 ";
                } else if (httpCode == 400 && "Invalid Url".equals(error)) {
                    errorMsg = "请求的 Method、Path 或者环境错误";
                } else if (httpCode == 400 && "Invalid Param Location".equals(error)) {
                    errorMsg = "参数错误";
                } else if (httpCode == 403 && "Unauthorized".equals(error)) {
                    errorMsg = "服务未被授权（或URL和Path不正确）";
                } else if (httpCode == 403 && "Quota Exhausted".equals(error)) {
                    errorMsg = "套餐包次数用完 ";
                } else {
                    errorMsg = "参数名错误 或 其他错误";
                }
            }

        } catch (MalformedURLException e) {
            errorMsg = "URL格式错误";
        } catch (UnknownHostException e) {
            errorMsg = "URL地址错误";
        } catch (Exception e) {
            errorMsg = e.getMessage();
            e.printStackTrace();
        }
        resultVO = new BankVerifyResultVO();
        resultVO.setCode(100);
        resultVO.setMsg(ResultEnums.BANK_CARD_VERIFY_ERROR.getMessage() + ":" + errorMsg);
        return resultVO;
    }

    @Override
    public BankVerifyResultVO doLocalVerify(BankVerifyDTO dto) {
        BankCardChekLog bankCardChekLog = logRepository.findById(dto.getAccountNo()).orElse(null);
        BankVerifyResultVO bankVerifyResultVO = new BankVerifyResultVO();
        bankVerifyResultVO.setCode(100);
        if (bankCardChekLog != null) {
            BeanUtils.copyProperties(bankCardChekLog, bankVerifyResultVO);
            bankVerifyResultVO.setCode(0);
            if (!bankCardChekLog.getIdCard().equals(dto.getIdCard())) {
                bankVerifyResultVO.setCode(100);
                bankVerifyResultVO.setMsg("身份证号输入错误");
                return bankVerifyResultVO;
            }
            if (!bankCardChekLog.getName().equals(dto.getName())) {
                bankVerifyResultVO.setCode(100);
                bankVerifyResultVO.setMsg("姓名输入错误");
                return bankVerifyResultVO;
            }
            if (!bankCardChekLog.getMobile().equals(dto.getMobile())) {
                bankVerifyResultVO.setCode(100);
                bankVerifyResultVO.setMsg("电话号码输入错误");
                return bankVerifyResultVO;
            }
        }

        return bankVerifyResultVO;
    }

    /*
     * 读取返回结果
     */
    private static String read(InputStream is) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String line = null;
        while ((line = br.readLine()) != null) {
            line = new String(line.getBytes(), StandardCharsets.UTF_8);
            sb.append(line);
        }
        br.close();
        return sb.toString();
    }

    @Autowired
    public void setLogRepository(BankCardChekLogRepository logRepository) {
        this.logRepository = logRepository;
    }
}
